package com.yupi.maker.generator.main;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.resource.ClassPathResource;
import cn.hutool.core.util.StrUtil;
import cn.hutool.core.util.ZipUtil;
import com.yupi.maker.generator.JarGenerator;
import com.yupi.maker.generator.ScriptGenerator;
import com.yupi.maker.generator.file.DynamicFileGenerator;
import com.yupi.maker.meta.Meta;
import com.yupi.maker.meta.MetaManager;
import freemarker.template.TemplateException;

import java.io.File;
import java.io.IOException;

/**
 * @version 1.0
 * @Author moresuo
 * @Date 2024/9/12 0:11
 * @注释 自动生成模板文件
 */
public abstract class GenerateTemplate {
    public void doGenerate() throws TemplateException, IOException, InterruptedException {
        //根据元信息配置文件生成对应的meta对象
        Meta meta = MetaManager.getMetaObject();

        //指定输出的根路径
        String projectPath = System.getProperty("user.dir");
        String outputPath = projectPath + File.separator + "yuzi-generator-maker" + File.separator + "generated"+File.separator+meta.getName();
        doGenerate(meta, outputPath);

    }

    public void doGenerate(Meta meta,String outputPath) throws TemplateException, IOException, InterruptedException {
        if(!FileUtil.exist(outputPath)){
            FileUtil.mkdir(outputPath);
        }

        //拷贝源文件到指定路径
        String sourceCopyDestPath = copySource(meta, outputPath);

        //制作代码生成器的源文件
        generateCode(meta, outputPath);

        //构建jar包
        String jarPath = buildJar(outputPath,meta);

        //封装脚本
        String shellOutputFilePath = buildScript(outputPath, jarPath);

        //生成精简版的产物压缩包
        buildDist(outputPath, sourceCopyDestPath, shellOutputFilePath, jarPath);

    }

    /**
     * 创建脚本文件
     * @param outputPath
     * @param jarPath
     * @return
     * @throws IOException
     */
    protected  String buildScript(String outputPath, String jarPath) throws IOException {
        String shellOutputFilePath = outputPath + File.separator + "generator";
        ScriptGenerator.doGenerate(shellOutputFilePath, jarPath);
        return shellOutputFilePath;
    }

    /**
     * 生成精简版，精简本只需要jar包和脚本文件即可执行，最好带有原始源文件
     * @param outputPath
     * @param sourceCopyDestPath
     * @param shellOutputFilePath
     * @param jarPath
     */
    protected   String buildDist(String outputPath, String sourceCopyDestPath, String shellOutputFilePath, String jarPath) {
        String distOutputPath = outputPath + "-dist";
        //拷贝jar包
        String targetAbsolutePath=distOutputPath+File.separator+"target";
        FileUtil.mkdir(targetAbsolutePath);
        String jarAbsolutePath= outputPath +File.separator+ jarPath;
        FileUtil.copy(jarAbsolutePath, targetAbsolutePath, true);

        //拷贝脚本文件
        FileUtil.copy(shellOutputFilePath, distOutputPath, true);
        FileUtil.copy(shellOutputFilePath +".bat", distOutputPath, true);
        //拷贝README.md
        FileUtil.copy(outputPath + File.separator + "README.md", distOutputPath, true);
        //拷贝原始文件
        FileUtil.copy(sourceCopyDestPath, distOutputPath, true);
        return distOutputPath;
    }

    /**
     * 自动打成jar包
     * @param outputPath
     * @param meta
     * @return
     * @throws IOException
     * @throws InterruptedException
     */
    protected  String buildJar(String outputPath,Meta meta) throws IOException, InterruptedException {
        JarGenerator.doGenerator(outputPath);
        String jarName=String.format("%s-%s-jar-with-dependencies.jar",meta.getName(),meta.getVersion());
        String jarPath="target/"+jarName;
        return jarPath;
    }

    /**
     * 构建代码生成器
     * @param meta
     * @param outputPath
     * @throws IOException
     * @throws TemplateException
     */
    protected   void generateCode(Meta meta, String outputPath) throws IOException, TemplateException {
        //读取resource目录
        ClassPathResource classPathResource=new ClassPathResource("/");
        String absolutePath = "";//模板文件目录

        //java包的基础路径
        String outputBasePackage= meta.getBasePackage();
        //将.分隔转为/分割
        String outputBasePath= StrUtil.join("/",StrUtil.split(outputBasePackage,"."));
        //generated/src/main/java/com/yupi
        String  outputDir= outputPath +File.separator+"src/main/java/"+outputBasePath;

        String inputFilePath;//模板文件输入路径
        String outputFilePath;//输出路径
        //model.DataModel
        inputFilePath = absolutePath + File.separator+"templates/java/model/DataModel.java.ftl";
        outputFilePath = outputDir + "/model/DataModel.java";
        DynamicFileGenerator.doGenerate(inputFilePath, outputFilePath, meta);

        // cli.command.ConfigCommand
        inputFilePath = absolutePath + File.separator + "templates/java/cli/command/ConfigCommand.java.ftl";
        outputFilePath = outputDir + "/cli/command/ConfigCommand.java";
        DynamicFileGenerator.doGenerate(inputFilePath , outputFilePath, meta);

        // cli.command.GenerateCommand
        inputFilePath = absolutePath + File.separator + "templates/java/cli/command/GenerateCommand.java.ftl";
        outputFilePath = outputDir + "/cli/command/GenerateCommand.java";
        DynamicFileGenerator.doGenerate(inputFilePath , outputFilePath, meta);

        // cli.command.ListCommand
        inputFilePath = absolutePath + File.separator + "templates/java/cli/command/ListCommand.java.ftl";
        outputFilePath = outputDir + "/cli/command/ListCommand.java";
        DynamicFileGenerator.doGenerate(inputFilePath , outputFilePath, meta);

        // cli.command.GenerateCommand
        inputFilePath = absolutePath + File.separator + "templates/java/cli/command/JsonGenerateCommand.java.ftl";
        outputFilePath = outputDir + "/cli/command/JsonGenerateCommand.java";
        DynamicFileGenerator.doGenerate(inputFilePath , outputFilePath, meta);

        // cli.CommandExecutor
        inputFilePath = absolutePath + File.separator + "templates/java/cli/CommandExecutor.java.ftl";
        outputFilePath = outputDir + "/cli/CommandExecutor.java";
        DynamicFileGenerator.doGenerate(inputFilePath , outputFilePath, meta);

        // Main
        inputFilePath = absolutePath + File.separator + "templates/java/Main.java.ftl";
        outputFilePath = outputDir + "/Main.java";
        DynamicFileGenerator.doGenerate(inputFilePath , outputFilePath, meta);

        // generator.DynamicGenerator
        inputFilePath = absolutePath + File.separator + "templates/java/generator/DynamicGenerator.java.ftl";
        outputFilePath = outputDir + "/generator/file/DynamicGenerator.java";
        DynamicFileGenerator.doGenerate(inputFilePath , outputFilePath, meta);

        // generator.MainGenerator.java.ftl
        inputFilePath = absolutePath + File.separator + "templates/java/generator/MainGenerator.java.ftl";
        outputFilePath = outputDir + "/generator/MainGenerator.java";
        DynamicFileGenerator.doGenerate(inputFilePath , outputFilePath, meta);

        // generator.StaticGenerator
        inputFilePath = absolutePath + File.separator + "templates/java/generator/StaticGenerator.java.ftl";
        outputFilePath = outputDir + "/generator/file/StaticGenerator.java";
        DynamicFileGenerator.doGenerate(inputFilePath , outputFilePath, meta);

        //pom.xml
        inputFilePath = absolutePath + File.separator + "templates/pom.xml.ftl";
        outputFilePath = outputPath + File.separator + "pom.xml";
        DynamicFileGenerator.doGenerate(inputFilePath , outputFilePath, meta);

        //生成README.md
        inputFilePath = absolutePath + File.separator + "templates/README.md.ftl";
        outputFilePath = outputPath + File.separator + "README.md";
        DynamicFileGenerator.doGenerate(inputFilePath , outputFilePath, meta);
    }

    /**
     * 拷贝原始文件到指定目录下
     * @param meta
     * @param outputPath
     * @return
     */
    protected  String copySource(Meta meta, String outputPath) {
        //从原始文件路径复制到生成的代码包中
        String sourceRootPath = meta.getFileConfig().getSourceRootPath();
        String sourceCopyDestPath= outputPath +File.separator+".source";
        FileUtil.copy(sourceRootPath,sourceCopyDestPath,true);
        return sourceCopyDestPath;
    }

    /**
     * 制作压缩包
     * @param outputPath
     * @return 压缩包路径
     */
    protected String buildZip(String outputPath) {
        String zipPath = outputPath + ".zip";
        ZipUtil.zip(outputPath, zipPath);
        return zipPath;
    }
}
